package de.dopichaj.labrador.search.hit;

import java.io.File;
import java.util.Comparator;

/**
 * Is used to compare hits with one another. Supports sorting
 * by score and sorting by path and XPath.
 * @author Benedikt
 */
public final class HitComparator implements Comparator<Hit> {

    public static final int SORT_BY_XPATH = 1000;
    public static final int SORT_BY_SCORE = 1001;
    
    private final int sortOrder;

    /**
     * Default constructor, sort by score.
     */
    public HitComparator() {
        sortOrder = SORT_BY_SCORE;
    }
    
    /**
     * Constructor
     * @param sortOrder One of the values SORT_BY_XPATH (sort by path, then ascending number of XPath parts)
     *                  or SORT_BY_SCORE (sort by descending score, then by ascending number of XPath parts)
     */
    public HitComparator(int sortOrder) {
        this.sortOrder = sortOrder;
    }

    /**
     * Compares two hits by the sort order specified in the 
     * constructor.
     * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
     */
    public int compare(Hit hit0, Hit hit1) {
        if(sortOrder == SORT_BY_SCORE) {
            int result = compareByScore(hit0.getScore(), hit1.getScore());
            if (result == 0) {
                return compareByXPath(hit0, hit1);
            } else {
                return result;
            }
        } else {
            return compareByXPath(hit0, hit1);
        }
    }

    /**
     * Compares two documents by XPath.
     */
    private int compareByXPath(final Hit hit0, final Hit hit1) {
        // sort by path first; then sort by xpath

        final File path0 = hit0.getFile();
        final File path1 = hit1.getFile();
        if (path0.compareTo(path1) < 0) {
            return -1;
        } else if (path0.compareTo(path1) > 0) {
            return 1;
        } else if (path0.compareTo(path1) == 0) {

            final int count0 = hit0.getDepth();
            final int count1 = hit1.getDepth();

            if (count0 != count1) {
                return (count0 > count1) ? 1 : -1;
            } else {
                final String[] parts0 = hit0.getXPathParts();
                final String[] parts1 = hit1.getXPathParts();
                for (int partNr = 0; partNr < count0; partNr++) {
                    final int cmp = parts1[partNr].compareTo(parts0[partNr]);
                    if (cmp != 0) {
                        return cmp;
                    }
                }
            }
            return 0;
        } else {
            throw new RuntimeException("Can't compare these two hits.");
        }
    }

    /**
     * Compares two scores.
     */
    private int compareByScore(double score0, double score1) {
        if(score0 < score1)
            return 1;
        else if(score0 > score1)
            return -1;
        else
            return 0;
    }
    
}
/*
Copyright (c) 2005 Benedikt Eger
Copyright (c) 2005-2007 Philipp Dopichaj

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/